#pragma once

#include <iostream>
#include <assert.h>
using namespace std;

class Date
{
	// 友元函数声明
	//如果成员函数变为私有，那么全局函数改为友元就可以使用，友元需要放在最前面
	friend ostream& operator<<(ostream& out, const Date& d); //流插入
	friend istream& operator>>(istream& in, Date& d); //流提取

public:
	Date(int year = 1900, int month = 1, int day = 1);
	
	//void Print();
	void Print() const; //修改成可以让const使用的

	// 直接定义在类里面，默认是inline
	int GetMonthDay(int year, int month)
	{
		assert(month > 0 && month < 13);
		
		// 用static 提高效率，创建一个静态区存进来，不用一直调用
		static int MonthDayArray[13] = { -1,31,28,31,30,31,30,31,31,30,31,30,31 };

		if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0) && month == 2)
		{
			return 29;
		}

		return MonthDayArray[month];
	}
	
	bool CheckDate();

	// const 加了是为了方便比较 Date* 和 const Date*
	bool operator<(const Date& d) const;
	bool operator<=(const Date& d) const;
	bool operator>(const Date& d) const;
	bool operator>=(const Date& d) const;
	bool operator==(const Date& d) const;
	bool operator!=(const Date& d) const;

	// const 不能修饰+= ,因为会使*this无法修改，因此要修改成员都不能用const

	// d1 + 100
	Date& operator+=(int day); //自身会改变
	Date operator+(int day) const;  // 自身不改变


	Date& operator-=(int day);
	Date operator-(int day) const; // d1 - 100
	int operator-(const Date& d) const; // d1 - d2

	// ++d1 返回++之后的值
	Date& operator ++();

	//d1++ 返回++之前的值
	//调用函数时该参数不用传递，编译器自动传递，因此不用传引用
	Date operator ++(int); //为了区分，构成重载，给后置++强行增加了一个int形参，可以不写形参名

	/*Date operator ++();
	Date &operator ++(int);*/

	Date& operator --();
	Date operator --(int);


	// 流插入,
	// 不建议，因为Date* this占据了一个参数位置，使用 d<<cout 不符合习惯
	//void operator<<(ostream& out);// 必须用引用ostream 不支持传值

private:
	int _year;
    int _month;
	int _day;
};


////重载 最好是全局，尽量不要是成员
//ostream& operator<<(ostream& out, const Date& d); //流插入
//istream& operator>>(istream& in, Date& d); //流提取
